package com.kevin.learn.thread;

/**
 * @ClassName: ThreadDemo
 * @Author: MrZf
 * @Date: 2021/3/9 14:44
 * @Description:
 * @Version: 1.0
 **/
public class ThreadDemo {

    private static volatile int type = 2;
    private static volatile int i = 0;
    private static volatile Object obj = new Object();
    
    public static void main(String[] args) throws InterruptedException {
//        synchMethodA();
        synchMethodB();
//        synchMethodC();
    }

    private static void synchMethodC() {
        Thread threadA = new Thread(new ThreadA());
        Thread threadB = new Thread(new ThreadB());
        Thread threadC = new Thread(new ThreadC());
        threadC.start();
        threadB.start();
        threadA.start();
    }

    private static void synchMethodB() {
        Thread threadA = new Thread(new ThreadA());
        Thread threadB = new Thread(new ThreadB());
        Thread threadC = new Thread(new ThreadC());
        threadC.start();
        threadB.start();
        threadA.start();
    }

    private static void synchMethodA() throws InterruptedException {
        Thread threadA = new Thread(new ThreadA());
        Thread threadB = new Thread(new ThreadB());
        Thread threadC = new Thread(new ThreadC());
        threadA.start();
        threadA.join();
        threadB.start();
        threadB.join();
        threadC.start();
        threadC.join();
    }

    static class ThreadA implements Runnable {
        
        @Override
        public void run()  {
            switch (type) {
                case 0:
                    System.out.println("ThreadA");
                    break;
                case 1:
                    synchronized (obj) {
                        while (i != 0) {
                            try {
                                obj.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println("ThreadA");
                        i = 1;
                        obj.notifyAll();
                    }
                    break;
                case 2:
                    while (i != 0) {
                        Thread.yield();
                    }
                    System.out.println("ThreadA");
                    i = 1;
                    break;
            }
        }
    }

    static class ThreadB implements Runnable {


        @Override
        public void run() {
            switch (type) {
                case 0:
                    System.out.println("ThreadB");
                    break;
                case 1:
                    synchronized (ThreadDemo.class) {
                        while (i != 1) {
                            try {
                                obj.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println("ThreadB");
                        i = 2;
                        obj.notifyAll();
                    }
                    break;
                case 2:
                    while (i != 1) {
                        Thread.yield();
                    }
                    System.out.println("ThreadB");
                    i = 2;
                    break;
            }
        }
    }

    static class ThreadC implements Runnable {

        @Override
        public void run() {
            switch (type) {
                case 0:
                    System.out.println("ThreadC");
                    break;
                case 1:
                    synchronized (obj) {
                        while (i != 2) {
                            try {
                                obj.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        System.out.println("ThreadC");
                        obj.notifyAll();
                    }
                    break;
                case 2:
                    while (i != 2) {
                        Thread.yield();
                    }
                    System.out.println("ThreadC");
                    break;
            }
        }
    }
}
